﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;

namespace IPCByMessages
{
    /// <summary>
    /// IPC message-oriented connection using sockets.
    /// To use it you must know hostname of machine where the second side is launched
    /// and tcp port at which interaction is organized.
    /// </summary>
    public abstract class MessagesChannelBase
    {
        #region Properties and fields

        /// <summary>
        /// Parser used to couple with packets
        /// </summary>
        protected MessageParser parser = new MessageParser();

        /// <summary>
        /// This side connection
        /// </summary>
        protected Socket connection;
        /// <summary>
        /// Other side connection
        /// </summary>
        protected Socket otherSide;

        /// <summary>
        /// Gets whether connection is Active.
        /// Connection can be used if Active = true.
        /// </summary>
        public bool Active { get; protected set; }

        /// <summary>
        /// Gets whether connection is closed.
        /// This instance cannot be used anymore if Closed = true
        /// </summary>
        public bool Closed { get; protected set; }
        
        #endregion

        #region Abstract methods

        /// <summary>
        /// Close connection and release all resources.
        /// Channel becomes not usable after call.
        /// </summary>
        public abstract void Close();

        /// <summary>
        /// Send message
        /// </summary>
        /// <param name="data">Data to send</param>
        public abstract void SendMessage(params byte[] data);
        
        #endregion

        #region Protected methods

        /// <summary>
        /// Throw Messagereceived event if Messagereceived is not null
        /// </summary>
        /// <param name="message">Message data</param>
        protected void ThrowMessageReceived(byte[] message)
        {
            if (MessageReceived != null)
                MessageReceived(this, new DataEventArgs(message));
        }

        /// <summary>
        /// Throw Disconnected event if Disconnected is not null
        /// </summary>
        protected void ThrowDisconnected()
        {
            if (Disconnected != null)
                Disconnected(this, EventArgs.Empty);
        }

        #endregion
        
        #region Events

        /// <summary>
        /// Occurs when new message received
        /// </summary>
        public event DataEventHandler MessageReceived;

        /// <summary>
        /// Occures when the connection is terminated by other side
        /// and data transfer becomes not available.
        /// After this event this instanse becomes  not usable anymore.
        /// </summary>
        public event EventHandler Disconnected;
        
        #endregion
    }
}
